<template>
  <li class="list-group-item d-flex justify-content-between align-item-center">
    <p :class="uploadItemClasses">
      <component :is="useIconFileType" />
      <span>{{ item.file.name }}</span>
    </p>
    <span class="failed-text" v-show="isCanceled">取消上传</span>
    <UploadControls
      :item="item"
      @cancel="handleCancel"
      @retry="handleRetry"
      @locate="handleLocate" />
  </li>
</template>

<script setup>
import { computed, reactive, onMounted, watch, inject } from 'vue'
import axios from 'axios'
import { iconFileType } from '../../../composable/icon-file-type'
import UploadControls from './UploadControls.vue'
import states from '../states'

const uploadItem = reactive(props.item)
let source = axios.CancelToken.source()

const createFormData = (file) => {
  const formData = new FormData()
  formData.append('file', file)
  return formData
}

const startUpload = async (upload, source) => {
  try {
    upload.state = states.UPLOADING
    const { data } = await axios.post('http://localhost:3030/files', createFormData(upload.file), {
      onUploadProgress: (e) => {
        //   console.log(e);
        if (e.lengthComputable) {
          upload.progress = Math.round((e.loaded / e.total) * 100)
        }
      },
      cancelToken: source.token,
    })
    upload.state = states.COMPLETE
    upload.response = data
  } catch (error) {
    if (axios.isCancel(error)) {
      upload.state = states.CANCELED
    } else {
      upload.state = states.FAILED
    }

    upload.progress = 0
  }
}

onMounted(startUpload(uploadItem, source))

const useIconFileType = computed(() => {
  return iconFileType(props.item.file.type)
})

const handleCancel = () => {
  source.cancel()
}

const handleRetry = () => {
  source = axios.CancelToken.source()
  startUpload(uploadItem, source)
}
const emits = defineEmits(['change', 'handleSelectChange'])
// 通过inject获取provide提供的数据或方法
const setSelectedItem = inject('setSelectedItem')
const handleLocate = () => {
  // emits("handleSelectChange", [uploadItem.response]);
  setSelectedItem([uploadItem.response])
}

const isCanceled = computed(() => uploadItem.state === states.CANCELED)

const uploadItemClasses = computed(() => {
  return {
    'upload-item': true,
    'failed': isCanceled.value,
  }
})

watch(
  () => uploadItem.state,
  () => {
    emits('change', uploadItem)
  }
)

const props = defineProps({
  item: {
    type: Object,
    required: true,
  },
})
</script>

<style scoped>
.upload-item {
  line-height: 2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
}

.upload-item,
.failed-text {
  color: #6c757d;
}

.upload-item span,
.failed-text {
  font-size: 12px;
}

.upload-item span {
  margin-left: 6px;
}

.failed {
  width: 140px;
  color: #212529;
}
</style>
